package ferp.android.dialogs;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.view.*;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.*;
import ferp.android.GUI;
import ferp.android.R;
import ferp.android.social.Connector;
import ferp.android.social.Post;
import ferp.android.tasks.center.TaskPublishReport;
import ferp.core.player.Profile;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * User: olegs
 * Date: 5/20/13 12:20 PM
 */
public class ShareDialog extends Dialog implements Connector.Listener.Login,
                                                   Connector.Listener.Post
{
  public static ShareDialog create(Context context, Profile profile)
  {
    return profile == null || profile.game() == null ? null : new ShareDialog(context, profile);
  }

  public void prepare()
  {
    SharedPreferences prefs = getContext().getSharedPreferences(Connector.SOCIAL, Context.MODE_PRIVATE);

    for (int i = 0; i < connectors.length; ++i)
    {
      Connector c = connectors[i];
      // do not use getOwnerActivity() here as it returns null (probably because the dialog is still not ready)
      Activity owner = (Activity)((ContextThemeWrapper)getContext()).getBaseContext();

      // set button's checked state according to stored and login states
      boolean loggedIn = c.isLoggedIn(owner);

      buttons[i].setChecked(prefs.getBoolean(SHARE_DIALOG + c.getClass().getSimpleName(), false) && loggedIn);
      c.getLogoutIcon(this).setVisibility(loggedIn ? View.GONE : View.VISIBLE);

      // save button state as it might be different from the stored one
      saveButtonState(c, buttons[i].isChecked());
    }

    setSendButtonState();
  }

  @Override
  public void onLoginFinished(int requestCode, boolean loggedIn)
  {
    switch (requestCode)
    {
      case Connector.RequestCode.OK:
        setButtonChecked(OK, loggedIn);
        break;

      case Connector.RequestCode.VK:
        setButtonChecked(VK, loggedIn);
        break;

      case Connector.RequestCode.FB:
        setButtonChecked(FB, loggedIn);
        break;

      case Connector.RequestCode.TW:
        setButtonChecked(TW, loggedIn);
        break;
    }
  }

  @Override
  public void onPostCompleted(Connector c, Connector.PostError error)
  {
    // add post result
    result.add(c, error);
    // stop animation
    ImageView clock = c.getProgressIcon(this);

    clock.clearAnimation();
    clock.setVisibility(View.GONE);

    // show toast only when all checked social networks have been posted (either successfully or not)
    if (result.isCompleted())
    {
      // create toast
      Toast t = createToast(R.layout.toast_post_result, R.id.toast_post_result_layout, R.id.toast_post_message, Gravity.CENTER);

      // show successfully posted social network icon
      for (Connector cn : result.success)
        cn.getPostToastIcon(t.getView()).setVisibility(View.VISIBLE);

      // show toast
      t.show();

      // report publish
      new TaskPublishReport(result.success, result.failure).execute();

      // dismiss the dialog
      dismiss();
    }
  }

  private ShareDialog(Context context, Profile profile)
  {
    super(context, R.layout.dialog_share, R.string.dialog_share_title);

    this.profile = profile;

    setCancelable(true);

    setupNote(R.id.dlg_share_note1);
    setupNote(R.id.dlg_share_note2);

    final EditText text = (EditText)findViewById(R.id.dlg_share_text);
    text.setTypeface(GUI.Font.NORMAL);

    resolveSocialButton(R.id.social_frame_layout_ok, R.drawable.selector_button_social_ok, OK, Connector.ok);
    resolveSocialButton(R.id.social_frame_layout_vk, R.drawable.selector_button_social_vk, VK, Connector.vk);
    resolveSocialButton(R.id.social_frame_layout_fb, R.drawable.selector_button_social_fb, FB, Connector.fb);
    resolveSocialButton(R.id.social_frame_layout_tw, R.drawable.selector_button_social_tw, TW, Connector.tw);

    send = resolveButton(R.id.dlg_element_footer_button, R.string.dialog_share_send_post);

    send.setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(View view)
      {
        Profile profile = ShareDialog.this.profile;

        // disable send button until the last post notification will received
        send.setEnabled(false);

        // prepare post result
        int sn = 0;

        for (ToggleButton b : buttons)
          if (b.isChecked())
            sn++;

        result.prepare(sn);

        // create and send post
        Activity owner = getOwnerActivity();
        Post post = Connector.createPost(owner, profile.game(), profile.settings, text.getText().toString().trim());

        for (int i = 0; i < buttons.length; ++i)
          if (buttons[i].isChecked())
          {
            Connector c = connectors[i];
            ImageView clock = c.getProgressIcon(ShareDialog.this);

            clock.setVisibility(View.VISIBLE);
            clock.startAnimation(animations[i]);

            c.post(ShareDialog.this, owner, post, profile.settings.locale);
          }
      }
    });

    for (int i = 0; i < animations.length; ++i)
      animations[i] = AnimationUtils.loadAnimation(context, R.anim.sand_clock_rotate);
  }

  private void setupNote(int id)
  {
    TextView note = (TextView)findViewById(id);

    note.setTypeface(GUI.Font.BOLD);
  }

  private void resolveSocialButton(int layoutID, int backgroundID, final int index, final Connector c)
  {
    connectors[index] = c;
    buttons[index] = resolveSocialButton(layoutID, backgroundID);

    buttons[index].setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(View view)
      {
        ToggleButton b = (ToggleButton)view;
        Activity a = getOwnerActivity();

        if (b.isChecked() && !c.isLoggedIn(a))
          c.login(ShareDialog.this, a, c.getRequestCode());
        else
          saveButtonState(c, b.isChecked());

        setSendButtonState();
      }
    });

    buttons[index].setOnLongClickListener(new View.OnLongClickListener()
    {
      @Override
      public boolean onLongClick(View view)
      {
        c.logout(getOwnerActivity());

        // create toast
        Toast t = createToast(R.layout.toast_social_logout, R.id.toast_social_logout_layout, R.id.toast_social_logout_message, Gravity.TOP);

        // show logged out social network icon
        c.getLogoutToastIcon(t.getView()).setVisibility(View.VISIBLE);

        // show toast
        t.show();

        ToggleButton b = (ToggleButton)view;
        b.setChecked(false);

        connectors[index].getLogoutIcon(ShareDialog.this).setVisibility(View.VISIBLE);

        return true;
      }
    });
  }

  private ToggleButton resolveSocialButton(int layoutID, int backgroundID)
  {
    ToggleButton tb = (ToggleButton)(findViewById(layoutID).findViewById(R.id.dlg_share_button));

    tb.setBackgroundResource(backgroundID);

    return tb;
  }

  private void setButtonChecked(int index, boolean loggedIn)
  {
    buttons[index].setChecked(loggedIn);
    connectors[index].getLogoutIcon(this).setVisibility(loggedIn ? View.GONE : View.VISIBLE);

    if (loggedIn)
      saveButtonState(connectors[index], true);

    setSendButtonState();
  }

  private void setSendButtonState()
  {
    int checked = 0;

    for (ToggleButton b : buttons)
      if (b.isChecked())
        ++checked;

    GUI.enableButton(send, checked > 0);
  }

  private void saveButtonState(Connector c, boolean checked)
  {
    SharedPreferences prefs = getContext().getSharedPreferences(Connector.SOCIAL, Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = prefs.edit();

    editor.putBoolean(SHARE_DIALOG + c.getClass().getSimpleName(), checked);
    editor.commit();
  }

  private Toast createToast(int resMain, int resRoot, int resText, int gravity)
  {
    // inflate toast view
    LayoutInflater inflater = getLayoutInflater();
    View view = inflater.inflate(resMain, (ViewGroup)findViewById(resRoot));

    TextView tv = (TextView)view.findViewById(resText);
    tv.setTypeface(GUI.Font.NORMAL);

    // create toast
    Toast toast = new Toast(getContext());

    toast.setGravity(gravity, 0, 0);
    toast.setDuration(Toast.LENGTH_LONG);
    toast.setView(view);

    return toast;
  }

  // preference
  private static final String SHARE_DIALOG = "share_dialog_";

  // number of social networks
  private static final int NUMBER_OF_NETWORKS = 4;

  // button indexes
  private static final int OK = 0;
  private static final int VK = 1;
  private static final int FB = 2;
  private static final int TW = 3;

  // connectors
  private Connector[] connectors = new Connector[NUMBER_OF_NETWORKS];

  // social buttons
  private ToggleButton[] buttons = new ToggleButton[connectors.length];
  // send button
  private Button send;

  // post results aggregation
  private static final class Result
  {
    private void prepare(int sn)
    {
      this.sn = sn;

      success.clear();
      failure.clear();
    }

    private void add(Connector c, Connector.PostError error)
    {
      if (error == null)
        success.add(c);
      else
        failure.put(c, error);
    }

    private boolean isCompleted()
    {
      return success.size() + failure.size() == sn;
    }

    // number of shares
    private int sn;
    // successfully posted connectors
    private final List<Connector> success = new LinkedList<Connector>();
    // unsuccessfully posted connectors
    private final Map<Connector, Connector.PostError> failure = new HashMap<Connector, Connector.PostError>();
  }

  private Profile profile;
  private Result result = new Result();
  private final Animation[] animations = new Animation[NUMBER_OF_NETWORKS];
}
